home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / displytl / xvjpeg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  10.8 KB  |  437 lines

  1. /*
  2.  * xvjpeg.c - i/o routines for 'jpeg' format pictures
  3.  *
  4.  * LoadJFIF(fname, numcols)  -  loads a JPEG pic, does 24to8 code if nec.
  5.  * WriteJFIF(fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
  6.  */
  7.  
  8. /*
  9.  * LoadJFIF Author: Markus Baur, University of Karlsruhe 
  10.  *                  (s_baur@iravcl.ira.uka.de)
  11.  * This software is provided "as is" without any express or implied warranty.
  12.  */
  13.  
  14. /* WriteJFIF() and JPEG dialog routines written by John Bradley */
  15.  
  16. /*
  17.  * Portions Copyright 1989, 1990, 1991, 1992 by John Bradley and
  18.  *                                The University of Pennsylvania
  19.  *
  20.  * Permission to use, copy, and distribute for non-commercial purposes,
  21.  * is hereby granted without fee, providing that the above copyright
  22.  * notice appear in all copies and that both the copyright notice and this
  23.  * permission notice appear in supporting documentation. 
  24.  *
  25.  * The software may be modified for your own purposes, but modified versions
  26.  * may not be distributed.
  27.  *
  28.  * This software is provided "as is" without any expressed or implied warranty.
  29.  *
  30.  * The author may be contacted via:
  31.  *    US Mail:   John Bradley
  32.  *               GRASP Lab, Room 301C
  33.  *               3401 Walnut St.  
  34.  *               Philadelphia, PA  19104
  35.  *
  36.  *    Phone:     (215) 898-8813
  37.  *    EMail:     bradley@cis.upenn.edu       
  38.  */
  39.  
  40.  
  41. #include "xvimage.h"
  42. #include "xvjinclude.h"
  43. #include <setjmp.h>
  44.  
  45.  
  46. /**** Stuff for JPEGDialog box ****/
  47.  
  48. #define JWIDE 280
  49. #define JHIGH 160
  50. #define J_NBUTTS 2
  51. #define J_BOK    0
  52. #define J_BCANC  1
  53. #define BUTTH    24
  54.  
  55. #ifdef __STDC__
  56. static void writeJPEG(void);
  57. #else
  58. static void drawJD(), doCmd(), clickJD(), writeJPEG();
  59. #endif
  60. static void jselwxv();
  61. static int writeJFIF();
  62.  
  63.  
  64. /* local variables */
  65. static char *filename;
  66. static int   colorType;
  67. static byte *image8, *image24;
  68.  
  69. static byte        *CurImagePtr;
  70. static byte        *pic24;
  71. static long          filesize;
  72. static jmp_buf      jmpState;
  73. static struct external_methods_struct   e_methods;
  74.  
  75.  
  76. /*********************************************/
  77. /**** INTERFACE CODE FOR THE JPEG LIBRARY ****/
  78. /*********************************************/
  79.  
  80.  
  81.  
  82. /********* JPEG DECOMPRESSION FUNCTIONS **********/
  83.  
  84. /**************************************************/
  85. static void xv_jpeg_monitor(cinfo, loopcnt, looplimit)
  86.      decompress_info_ptr cinfo;
  87.      long loopcnt, looplimit;
  88. {
  89.   int a,b;
  90.   double percent;
  91.  
  92. #ifdef FOO  
  93.   a = cinfo->completed_passes;
  94.   b = cinfo->total_passes;
  95.  
  96.   percent = ((a + ((double) loopcnt / looplimit)) / (double) b) * 100.0;
  97.  
  98.   fprintf(stderr,"jpeg: %lf done.  loop: %ld, %ld  pass: %d, %d\n",
  99.       percent, loopcnt, looplimit, a, b);
  100. #endif
  101. }
  102.  
  103.  
  104. /**************************************************/
  105. static void d_ui_method_selection(cinfo)
  106.      decompress_info_ptr cinfo;
  107. {
  108.   int i;
  109.  
  110.   /* select output colorspace & quantization parameters */
  111.   if (cinfo->jpeg_color_space == CS_GRAYSCALE) {
  112.     cinfo->out_color_space = CS_GRAYSCALE;
  113.     cinfo->quantize_colors = FALSE;
  114.     printf("Greyscale JPEG. (%ld bytes)\n", filesize);
  115.     /* fill in a greyscale colormap */
  116.     for (i=0; i<=255; i++)
  117.       r[i] = g[i] = b[i] = i;
  118.   }
  119.  
  120.   else {
  121.     cinfo->out_color_space = CS_RGB;
  122.  
  123.     if (conv24 == CONV24_FAST || conv24 == CONV24_SLOW)
  124.          cinfo->quantize_colors = TRUE;
  125.     else cinfo->quantize_colors = FALSE;
  126.  
  127.     if (conv24 != CONV24_FAST) cinfo->two_pass_quantize = TRUE;
  128.     else {
  129.       cinfo->two_pass_quantize = FALSE;
  130.       /* For the 1-pass quantizer it's best to use 256 colors and let */
  131.       /* the cmap sorter pick up any slack.  This produces essentially */
  132.       /* the same results as xv's usual fast quantizer, but it reduces */
  133.       /* swapping since no 24-bit copy of the image is needed. */
  134.       cinfo->desired_number_of_colors = 256;
  135.     }
  136.     printf("Color JPEG. (%ld bytes)\n", filesize);
  137.   }
  138.  
  139.   jselwxv(cinfo);
  140. }
  141.  
  142.  
  143. /**************************************************/
  144. static void output_init (cinfo)
  145.      decompress_info_ptr cinfo;
  146. {
  147.   pWIDE = cinfo->image_width;
  148.   pHIGH = cinfo->image_height;
  149.  
  150.   if (cinfo->out_color_space == CS_GRAYSCALE || 
  151.       cinfo->quantize_colors == TRUE) {
  152.     pic = (byte *) malloc(pWIDE * pHIGH);
  153.     if (!pic) FatalError("Not enough memory for Image");
  154.     CurImagePtr = pic;
  155.   }
  156.  
  157.   else {
  158.     pic24 = (byte *) malloc(pWIDE * pHIGH * 3);
  159.     if (!pic24) FatalError("Not enough memory for Image");
  160.     CurImagePtr = pic24;
  161.   }
  162. }
  163.  
  164.  
  165. /**************************************************/
  166. static void put_color_map (cinfo, num_colors, colormap)
  167.      decompress_info_ptr cinfo;
  168.      int num_colors;
  169.      JSAMPARRAY colormap;
  170. {
  171.   int i;
  172.  
  173.   for (i = 0; i < num_colors; i++) {
  174.     r[i] = GETJSAMPLE(colormap[0][i]);
  175.     g[i] = GETJSAMPLE(colormap[1][i]);
  176.     b[i] = GETJSAMPLE(colormap[2][i]);
  177.   }
  178. }
  179.  
  180.  
  181. /**************************************************/
  182. static void put_pixel_rows (cinfo, num_rows, pixel_data)
  183.      decompress_info_ptr cinfo;
  184.      int                 num_rows;
  185.      JSAMPIMAGE          pixel_data;
  186. {
  187.   JSAMPROW ptr0, ptr1, ptr2;
  188.   long col;
  189.   long width = cinfo->image_width;
  190.   int row;
  191.   static unsigned int totrows = 0;
  192.  
  193.   if (cinfo->out_color_space == CS_GRAYSCALE || 
  194.       cinfo->quantize_colors == TRUE) {
  195.  
  196.     for (row = 0; row < num_rows; row++) {
  197.       ptr0 = pixel_data[0][row];
  198.       for (col = width; col > 0; col--) {
  199.     *CurImagePtr++ = GETJSAMPLE(*ptr0++);
  200.       }
  201.       totrows++;
  202.     }
  203.   }
  204.  
  205.   else {
  206.     for (row = 0; row < num_rows; row++) {
  207.       ptr0 = pixel_data[0][row];
  208.       ptr1 = pixel_data[1][row];
  209.       ptr2 = pixel_data[2][row];
  210.       for (col = width; col > 0; col--) {
  211.     *CurImagePtr++ = GETJSAMPLE(*ptr0++);
  212.     *CurImagePtr++ = GETJSAMPLE(*ptr1++);
  213.     *CurImagePtr++ = GETJSAMPLE(*ptr2++);
  214.       }
  215.       totrows++;
  216.     }
  217.   }
  218. }
  219.  
  220.  
  221. /**************************************************/
  222. static void output_term (cinfo)
  223.      decompress_info_ptr cinfo;
  224. {
  225.   /* no work required */
  226. }
  227.  
  228.  
  229. /**************************************************/
  230. static void jselwxv(cinfo)
  231.      decompress_info_ptr cinfo;
  232. {
  233.   cinfo->methods->output_init = output_init;
  234.   cinfo->methods->put_color_map = put_color_map;
  235.   cinfo->methods->put_pixel_rows = put_pixel_rows;
  236.   cinfo->methods->output_term = output_term;
  237. }
  238.  
  239.  
  240. /**************************************************/
  241. static void JPEG_Message (msgtext)
  242.      char *msgtext;
  243. {
  244.   char tempstr[200];
  245.  
  246.   sprintf(tempstr, msgtext,
  247.       e_methods.message_parm[0], e_methods.message_parm[1],
  248.       e_methods.message_parm[2], e_methods.message_parm[3],
  249.       e_methods.message_parm[4], e_methods.message_parm[5],
  250.       e_methods.message_parm[6], e_methods.message_parm[7]);
  251.   printf("%s\n", tempstr);
  252. }
  253.  
  254.  
  255. /**************************************************/
  256. static void JPEG_Error (msgtext)
  257.      char *msgtext;
  258. {
  259.   char tempstr[200];
  260.  
  261.   sprintf(tempstr, msgtext,
  262.       e_methods.message_parm[0], e_methods.message_parm[1],
  263.       e_methods.message_parm[2], e_methods.message_parm[3],
  264.       e_methods.message_parm[4], e_methods.message_parm[5],
  265.       e_methods.message_parm[6], e_methods.message_parm[7]);
  266.   printf("%s\n", tempstr);
  267.   longjmp(jmpState,1);
  268. }
  269.  
  270.  
  271. /*******************************************/
  272. int LoadJFIF(fname,nc)
  273.      char *fname;
  274.      int   nc;
  275. /*******************************************/
  276. {
  277.   int rtval;
  278.   struct decompress_info_struct    cinfo;
  279.   struct decompress_methods_struct dc_methods;
  280.  
  281.   /* Set up the input file */
  282.  
  283.   if ((cinfo.input_file = fopen(fname, "r")) == NULL) return 1;
  284.  
  285.   /* figure out the file size (for Informational Purposes Only) */
  286.   fseek(cinfo.input_file, 0L, 2);
  287.   filesize = ftell(cinfo.input_file);
  288.   fseek(cinfo.input_file, 0L, 0);
  289.  
  290.   cinfo.output_file = NULL;    /* only wanna read */
  291.  
  292.   pic24 = (byte *) NULL;
  293.  
  294.   /* Set up longjmp for error recovery out of JPEG_Error */
  295.   rtval = setjmp(jmpState);
  296.   if (rtval) {
  297.     fclose(cinfo.input_file);    /* close input file */
  298.     return rtval;        /* no further cleanup needed */
  299.   }
  300.  
  301.   /* Initialize the system-dependent method pointers. */
  302.   cinfo.methods  = &dc_methods;
  303.   cinfo.emethods = &e_methods;
  304.   e_methods.error_exit = JPEG_Error; /* provide my own error/message rtns */
  305.   e_methods.trace_message = JPEG_Message;
  306.   e_methods.trace_level = 0;    /* no tracing, thank you */
  307.   jselmemmgr(&e_methods);    /* memory allocation routines */
  308.   dc_methods.d_ui_method_selection = d_ui_method_selection;
  309.  
  310.   /* Set up default JPEG parameters. */
  311.   j_d_defaults(&cinfo, TRUE);
  312.   /* the jpeg quantizer can't handle small values of 'nc' */
  313.   cinfo.desired_number_of_colors = (nc<16) ? 255 : nc;
  314.   
  315.   /* set up our progress-monitoring function */
  316. /*  cinfo.methods->progress_monitor = xv_jpeg_monitor;  */
  317.   
  318.   /* Set up to read a JFIF or baseline-JPEG file. */
  319.   /* A smarter UI would inspect the first few bytes of the input file */
  320.   /* to determine its type. */
  321.   jselrjfif(&cinfo);
  322.   
  323.   /* Do it! */
  324.   jpeg_decompress(&cinfo);
  325.  
  326.   if (pic24) {
  327.     /* call XV's quantizer */
  328.     Conv24to8(pic24, pWIDE, pHIGH, nc);
  329.     free(pic24);
  330.   }
  331.  
  332.   /* Close input file */
  333.   fclose(cinfo.input_file);
  334.   
  335.   sprintf(formatStr, "%dx%d %s JPEG. ", cinfo.image_width, cinfo.image_height, 
  336.       (cinfo.out_color_space == CS_GRAYSCALE) ? "Greyscale " : "Color ");
  337.   
  338.   /* Got it! */
  339.   return 0;
  340. }
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347. /********* JPEG COMPRESSION FUNCTIONS **********/
  348.  
  349.  
  350. /**************************************************/
  351. static void c_ui_method_selection(cinfo)
  352.      compress_info_ptr cinfo;
  353. {
  354.   /* select output colorspace */
  355.   if (colorType == F_GREYSCALE) {
  356.     j_monochrome_default(cinfo);
  357.   }
  358. }
  359.  
  360.  
  361. /**************************************************/
  362. static void input_init (cinfo)
  363.      compress_info_ptr cinfo;
  364. {
  365.   int w,h;
  366.  
  367.   if (colorType == F_GREYSCALE) {
  368.     cinfo->input_components = 1;
  369.     cinfo->in_color_space = CS_GRAYSCALE;
  370.     CurImagePtr = image8;
  371.   }
  372.  
  373.   else {
  374.     cinfo->input_components = 3;
  375.     cinfo->in_color_space = CS_RGB;
  376.     CurImagePtr = image24;
  377.   }
  378.  
  379. /*
  380.   if (savenormCB.val) { w = cWIDE;  h = cHIGH; }
  381.                  else { w = eWIDE;  h = eHIGH; }
  382. */
  383.   cinfo->image_width  = w;
  384.   cinfo->image_height = h;
  385.   cinfo->data_precision = 8;
  386. }
  387.  
  388.  
  389. /**************************************************/
  390. static void get_input_row(cinfo, pixel_row)
  391.      compress_info_ptr cinfo;
  392.      JSAMPARRAY        pixel_row;
  393. {
  394.   JSAMPROW ptr0, ptr1, ptr2;
  395.   long col;
  396.   static unsigned int totrows = 0;
  397.  
  398.   if (cinfo->input_components == 1) {
  399.     ptr0 = pixel_row[0];
  400.     for (col = cinfo->image_width; col > 0; col--) {
  401.       *ptr0++ = *CurImagePtr++;
  402.     }
  403.     totrows++;
  404.   }
  405.  
  406.   else {
  407.     ptr0 = pixel_row[0];
  408.     ptr1 = pixel_row[1];
  409.     ptr2 = pixel_row[2];
  410.     for (col = cinfo->image_width; col > 0; col--) {
  411.       *ptr0++ = *CurImagePtr++;
  412.       *ptr1++ = *CurImagePtr++;
  413.       *ptr2++ = *CurImagePtr++;
  414.     }
  415.     totrows++;
  416.   }
  417. }
  418.  
  419.  
  420. /**************************************************/
  421. static void input_term (cinfo)
  422.      compress_info_ptr cinfo;
  423. {
  424.   /* no work required */
  425. }
  426.  
  427.  
  428. /**************************************************/
  429. static void jselrxv(cinfo)
  430.      compress_info_ptr cinfo;
  431. {
  432.   cinfo->methods->input_init = input_init;
  433.   cinfo->methods->get_input_row = get_input_row;
  434.   cinfo->methods->input_term = input_term;
  435. }
  436.  
  437.